我們用 SMART——Specific(具體)、Measurable(可衡量)、Achievable(可達成)、Relevant(具關聯)、Time-bound(有時限)——把每個故事拆成五天,作為每次動手造輪子前的五個檢查問題。
本篇是故事四「從 ONVIF 攝影機截圖太難了,我們來搞 V4L2」的 Achievable 篇:利用現有工具與最小變更,做得到嗎?
本篇定位:提出從標準能力到替代方案的漸進式實作順序。
驗收表逼我們回頭給標準路徑一次公平的審判。這次先找現成工具,不再硬啃規格書。ONVIF 是被廣泛採用的產業標準,規格公開,社群早有開源的用戶端程式庫與測試工具可用(官方的一致性測試工具則要有會員資格)。裝好之後,那些嚇人的 SOAP 與 WSDL 全被包進了幾個函式呼叫。
步驟感是這樣的。先連上裝置管理服務的固定進入點 http://<裝置IP>/onvif/device_service,帶上認證資訊;呼叫 GetServices,讓設備自己列出支援哪些服務與各自的位址(舊的 GetCapabilities 還在,但現在的定位是向後相容);對 Media 服務呼叫 GetProfiles 取得媒體設定檔清單,挑出符合需求的那一份,記下它的設定檔識別碼;帶著那個識別碼呼叫 GetSnapshotUri,設備回一個網址;最後用一次帶認證的 HTTP GET 打開它,把影像抓下來。
有一個當時沒注意、後來卻決定了梯子形狀的細節:GetSnapshotUri 在 Media 服務規格裡屬於條件式功能——設備的 SnapshotUri 能力宣告為 true 時才必須支援,通過 Profile T 認證的設備則是必要功能。標準給了你問的方法,沒有保證答案一定存在。
回來的那張圖也要當場檢查。規格保證編碼一定是 JPEG,但解析度與品質的規格用字是「若適當時應取自該設定檔」——是「應」而非強制,各廠牌實作未必一致。影像到手後要自己量一次實際尺寸,別假設它一定照著設定檔走。
整段流程短得出乎意料,每一步都對得上驗收表的一列,花掉的時間比當初那兩天少得多。差別不在人變聰明了,而在問法變了:當初想把整份協定看懂,這次只問「我的需求對應哪一小塊,誰已經把它包好了」。
當初卡住不是因為 ONVIF 難,而是我們把「看懂整份協定」當成了使用門檻。規格書是寫給實作者的;使用者只需要碰需求對應的那一小塊,而那一小塊幾乎都有現成的封裝。那失敗的兩天,時間全花在讀規格書上,卻沒有一段是花在找程式庫——我們用實作者的姿勢,去做使用者的事。
另一個問題是手上沒有梯子。標準路徑一受挫,我們沒有「下一步該試什麼」的順序,於是從最上層直接跳到最底層,中間的選項全被略過。而被跳過的每一級,都是別人已經替你承擔掉的責任:協定有人定了、解碼有人寫了、設備內部有原廠顧著。跳得愈深,撿回來自己扛的就愈多。
把梯子補上。取得攝影機影像的路徑,依侵入程度由淺到深是:
清單的重點不是順序本身,是它其實是一道責任的斜坡:每一級要付出什麼、要什麼證據才准往下走。
第一級幾乎不花錢:翻規格書與設備的網頁介面,確認它宣告的一致性規範與有沒有列出截圖能力。往下一級的理由很單純——文件看完了,該實測了。
第二級是標準的正門,代價是裝一套程式庫、學幾個操作的語意;能不能滿足需求,由 GetProfiles 與 GetSnapshotUri 的回應直接回答。往下一級的條件很硬:設備明確沒有 Media 服務,或有媒體設定檔卻不給可用的 Snapshot URI,而且錯誤有紀錄。前面那個「條件式功能」正是這一級會失手的原因,也是第三級非存在不可的理由。
第三級是繞路。用現成的多媒體工具透過 RTSP 把串流拉起來,聽起來只是多幾個步驟,實際上是接手一整套即時傳輸的問題。H.264/H.265 的畫面不能隨便從中間切:必須先取得參數集(H.264 的 SPS/PPS,H.265 另有 VPS),再等到一個關鍵影格(IDR,隨機存取點),才重建得出完整畫面——這正是「按下去馬上要圖」會等的原因。載送影像的 RTP 通常跑在 UDP 上,本身不保證送達與順序,封包掉了畫面就破;改走 RTP over TCP(interleaved 模式)讓影像與控制訊息共用同一條連線,可以穿越防火牆,代價是延遲與擁塞時的堆積。再加上會話的建立與釋放,以及「哪一格才算當下」這個新問題:原本一次請求換一張圖,現在要維護一段連線。只有設備真的沒有單張截圖介面,這成本才划算。
第四級的廠商正式 API 或 SDK 是相容層,不是禁區:官方支援、有文件、不動設備內部,本來就是階梯上正當的一級。代價是綁定特定廠商生態,換品牌得重寫一份;走到這級的前提,是標準路徑在這個型號上被證實有缺口,而這台設備又非用不可。至於論壇上查來的那條路徑不算這一級:沒有文件、沒有承諾,連相容層都稱不上。
第五級已經不是技術選項,是接管別人的產品內部,後果晚一點再細算;准入條件無關做不做得到,而在有沒有人願意簽下後續的維護責任。
每往下一級,都該有上一級的失敗證據墊底,而且證據必須是「試過、確實不支援、有紀錄」,不能是「我不會」。這也是驗收表的另一個用途:每一級都拿同一張表來驗,過了就停在這一級,不過才帶著紀錄往下走。要問的始終是最淺的哪一級就夠。
先把門、門鈴與鑰匙都試過,再決定是否真的需要拆牆。階梯的價值不在限制人,而在把「不會」與「不支援」分開:前者的解法是找工具、查文件、換一種問法,後者才構成往下一級的理由。這次在第二級就到了終點。
會後有人不服氣:「可是 V4L2 那條路,我們真的走得通啊。」這句話沒有說錯,也正因為沒說錯,才值得認真回答——走得通,跟解決我們的問題,是兩回事。